using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using SoundTouchNet;

/// Contiene los botones para REPRODUCIR y para CREAR y COMPARTIR el video
public class GUIManagerVoice : MonoBehaviour
{
	public GUISkin mSkin;

	Rect rectButtonPlay;
	Rect rectButtonRec;
	Rect rectButtonShare;
	Rect rectButtonHome;

	bool bRec=false;
	bool bPlay=false;
	bool bExport=false;

	bool bRecOld=false;
	bool bPlayOld=false;

	AudioClip audioClip;
	const int totalTime = 15;
	const int frequency = 44100;
	const int channels = 1;

	int video_w = Screen.width;
	int video_h = Screen.height;

	float mCurrentTime;
	float CurrentTime{
		get{ return mCurrentTime;}
		set{ 
			mCurrentTime=value;
			SetTime((int)Mathf.Min(value,15.0f));
		}
	}

	public GUIText mTextTime;
	public GUIText mTextTimeShadow;

	GameObject mCurrentCharacter;

	int shiftMosquito=4;

	AudioFilters filter;

	public iVidCapPro vr;
	int iFramesRecorded=0;

	bool bShowMsg=false;
	float iTimeMsg=0;
	const int iMaxTimeMsg=3;

	float ratio;
	int fontSize;

	/*
	private IntPtr m_handle = IntPtr.Zero;
	float newPitch = 3.0f;
	
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	[DllImport("SoundTouchNet", CallingConvention = CallingConvention.StdCall)]
	private static extern IntPtr soundtouch_createInstance();

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///Apply filter using SoundTouch
	///http://www.surina.net/soundtouch/
	void ApplyFilter_SoundTouch()
	{
		//Create SoundTouch instance
		if(m_handle != IntPtr.Zero){
			Debug.Log("SoundSharp Instance was already initialized but not destroyed. Use DestroyInstance().");
		}
		m_handle = soundtouch_createInstance();

		//Set sample rate and channels
		SoundTouch.soundtouch_setSampleRate(m_handle, frequency);
		SoundTouch.soundtouch_setChannels(m_handle, channels);

		//*********** Queda pendiente añadir las muestras al SoundTouch y procesarlas ***********
		//SoundTouch.soundtouch_putSamples(m_handle, 

		//Verify instance initialized
		if(m_handle == IntPtr.Zero){
			Debug.Log("SoundTouch as not initialized. Use CreateInstance()");
		}
		else{
			//Change pitch
			SoundTouch.soundtouch_setPitch(m_handle, newPitch);

			//Destroy SoundTouch instance
			if(m_handle != IntPtr.Zero){
				SoundTouch.soundtouch_destroyInstance(m_handle);
				m_handle = IntPtr.Zero;
			}
		}
	}
	*/
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void Start()
	{
		rectButtonPlay = new Rect(Screen.width/2-ButtonProps.buttonSize-ButtonProps.buttonMargin/2, Screen.height-ButtonProps.buttonSize-ButtonProps.buttonMargin, ButtonProps.buttonSize, ButtonProps.buttonSize);
		rectButtonRec = new Rect(Screen.width/2+ButtonProps.buttonMargin/2, Screen.height-ButtonProps.buttonSize-ButtonProps.buttonMargin, ButtonProps.buttonSize, ButtonProps.buttonSize);
		rectButtonShare = new Rect(Screen.width-ButtonProps.buttonSize-15, Screen.height-ButtonProps.buttonSize-ButtonProps.buttonMargin, ButtonProps.buttonSize, ButtonProps.buttonSize);
		rectButtonHome = new Rect(Screen.width-ButtonProps.buttonSize-ButtonProps.buttonMargin*0.5f, ButtonProps.buttonMargin*0.5f, ButtonProps.buttonSize, ButtonProps.buttonSize);

		audio.loop = false;
		audio.playOnAwake = false;
		audio.clip = null;
		
		audioClip = new AudioClip();

		string charName = PlayerPrefs.GetString("CurrentChar");
		mCurrentCharacter = Instantiate(Resources.Load("Prefabs/Characters/"+charName, typeof(GameObject)) as GameObject) as GameObject;
		mCurrentCharacter = mCurrentCharacter.transform.FindChild("mesh").gameObject;

		filter = new AudioFilters();

		ratio = Screen.width/480.0f;
		fontSize = (int)(22*ratio);
		mSkin.GetStyle("styleMsg").fontSize = fontSize;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void OnGUI()
	{
		GUI.skin = mSkin;

		//REC
		GUI.enabled = !bPlay && !bExport;
		bRec = GUI.Toggle(rectButtonRec, bRec, "", "rec");
		if(bRec!=bRecOld){
			bRecOld=bRec;
			OnButtonTimeVoiceRecChecked(bRec);
		}
		GUI.enabled = true;

		//PLAY
		GUI.enabled = audioClip!=null && !bRec && !bExport;
		bPlay = GUI.Toggle(rectButtonPlay, bPlay, "", "play");
		if(bPlay!=bPlayOld){
			bPlayOld=bPlay;
			OnButtonTimeVoicePlayChecked(bPlay);
		}
		GUI.enabled = true;

		//SHARE (EXPORT)
		GUI.enabled = !bExport && audioClip!=null && !bPlay && !bRec;
		if(GUI.Button(rectButtonShare, "", "share")){
			bExport=true;
			OnButtonTimeVoiceShareChecked();
		}
		GUI.enabled = true;

		//HOME
		if(GUI.Button(rectButtonHome, "", "home")){
			Application.LoadLevel("00 Main");
		}

		if(bShowMsg){
			GUI.Label(new Rect(0, Screen.height/2, Screen.width, 200), "VIDEO GUARDADO EN LA GALERIA", "styleMsg");
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void Update()
	{
		if(bRec){
			//Recording
			if(Microphone.IsRecording(null)){
				CurrentTime += Time.deltaTime;
			}
			//Max.time reached
			else{
				bRec=false;
				SetColor(Color.white);
			}
		}
		else if(bPlay){
			//Playing
			if(CurrentTime < audio.clip.length){
				CurrentTime += Time.deltaTime;
			}
			//End playing
			else{
				audio.Stop();
				if(mCurrentCharacter.animation!=null){
					mCurrentCharacter.animation.Stop();
				}
				bPlay=false;
			}
		}
		else if(bExport){
			if(CurrentTime < audio.clip.length){
				CurrentTime += Time.deltaTime;
			}
			//End export
			else{
				audio.Stop();
				if(mCurrentCharacter.animation!=null){
					mCurrentCharacter.animation.Stop();
				}
				bExport=false;
				vr.EndRecordingSession(iVidCapPro.VideoDisposition.Save_Video_To_Album, out iFramesRecorded);
				if(iFramesRecorded<10){
					Debug.Log("******************* ivcp: Frames recorded < 10");
				}
				bShowMsg=true;
			}
		}

		if(bShowMsg){
			if(iTimeMsg<iMaxTimeMsg){
				iTimeMsg+=Time.deltaTime;
			}else{
				bShowMsg=false;
				iTimeMsg=0;
			}
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//REC
	public void OnButtonTimeVoiceRecChecked(bool bActivate)
	{
		//Start recording
		if(bActivate){
			ResetAudio();
			audioClip = Microphone.Start(null, false, totalTime, frequency);
			SetColor(Color.red);
			CurrentTime=0;
		}
		//Stop recording
		else{
			if(audioClip != null) {
				Microphone.End(null);
				ApplyFilter();
				RemoveEmptyData();
			}
			SetTime((int)Mathf.Max(1.0f,CurrentTime));
			SetColor(Color.white);
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//PLAY
	public void OnButtonTimeVoicePlayChecked(bool bActivate)
	{
		//Start playing
		if(bActivate){
			audio.clip=audioClip;
			audio.Play();
			if(mCurrentCharacter.animation!=null){
				mCurrentCharacter.animation.Play();
			}
			CurrentTime=0;
		}
		//Stop playing
		else{
			audio.Stop();
			if(mCurrentCharacter.animation!=null){
				mCurrentCharacter.animation.Stop();
			}
			SetTime((int)audioClip.length);
		}
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//SHARE
	public void OnButtonTimeVoiceShareChecked()
	{
		audio.clip=audioClip;
		audio.Play();
		if(mCurrentCharacter.animation!=null){
			mCurrentCharacter.animation.Play();
		}
		CurrentTime=0;

		vr.BeginRecordingSession("mi_video", video_w, video_h, 25, iVidCapPro.CaptureAudio.Audio, iVidCapPro.CaptureFramerateLock.Unlocked);
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public void ResetAudio()
	{
		if(audioClip != null){
			DestroyImmediate(audioClip);
		}
		audioClip = null;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///Remove empty sound at the end of the file
	void RemoveEmptyData()
	{
		float[] samples = new float[audioClip.samples * audioClip.channels];
		audioClip.GetData(samples, 0);
		
		float recordTime = Mathf.Max(CurrentTime, 0.5f); //0.5sec minimum record time
		
		int count = 0;
		int trim = Mathf.CeilToInt(recordTime * frequency);
		if(trim > samples.Length)
			trim = samples.Length;
		for(int i = trim - 1; i > 0; --i) {
			if(samples[i] != 0f)
				break;
			else
				++count;
		}
		
		int size = Mathf.Max(trim - count, (int)(frequency * 0.5f));
		float[] samplesTrim = new float[size];
		
		Buffer.BlockCopy(samples, 0, samplesTrim, 0, samplesTrim.Length * sizeof(float));
		
		audioClip = AudioClip.Create("user_clip", samplesTrim.Length, channels, frequency, false, false);
		audioClip.SetData(samplesTrim, 0);
		
		samples = null;
		samplesTrim = null;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public void SetTime(int seconds)
	{
		mTextTime.text = "00:"+seconds.ToString("00");
		mTextTimeShadow.text = mTextTime.text;
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	public void SetColor(Color color)
	{
		mTextTime.color = color;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void ApplyFilter()
	{
		float[] indata = new float[audioClip.samples * audioClip.channels];
		float[] outdata = new float[audioClip.samples * audioClip.channels];

		audioClip.GetData(indata, 0);
		filter.Mosquito(indata, out outdata, shiftMosquito);
		audioClip.SetData(outdata, 0);

		CurrentTime = (int)audioClip.length;
	}
}















